import re
from typing import Any

from aiogram import Bot, types
from aiogram.types import ContentType, FSInputFile
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.input import MessageInput
from aiogram_dialog.widgets.kbd import Back, Button, Cancel
from aiogram_dialog.widgets.text import Const
from sqlalchemy.ext.asyncio import AsyncSession

from app.bot.dialogs.dialog_state import AddBookSG
from app.bot.utils.logger import logger
from app.config import Settings
from app.database.requests import add_book


async def process_book_post(
    message: types.Message, dialog: Dialog, manager: DialogManager
):
    bot: Bot = manager.middleware_data.get("bot")

    file = await bot.get_file(message.photo[-1].file_id)

    file_path = file.file_path
    destination_path = f"app/bot/{file_path}"
    destination_path = destination_path.replace("photos", "files/covers")

    book_post = message.caption
    try:
        book_title = re.findall("^([^\n]+)", book_post)[0]
        book_level = re.findall(r"([ABC]\d)", book_post)[0]

        book_post = book_post.replace(book_title, "").strip()

        manager.dialog_data["book_post"] = book_post
        manager.dialog_data["book_title"] = book_title
        manager.dialog_data["book_level"] = book_level
        manager.dialog_data["book_cover"] = destination_path

        await bot.download_file(file_path, destination_path)
        await manager.switch_to(AddBookSG.send_book_file)

    except IndexError:
        await message.answer("Не могу получить название и уровень книги из описания")


async def process_book_file(
    message: types.Message, dialog: Dialog, manager: DialogManager
):
    bot: Bot = manager.middleware_data.get("bot")

    file = await bot.get_file(message.document.file_id)

    file_path = file.file_path
    destination_path = f"app/bot/files/books/{message.document.file_name}"
    manager.dialog_data["book_filename"] = destination_path

    quote = message.caption

    msg = await message.answer("Скачиваю файл")

    await bot.download_file(file_path, destination_path)

    await msg.delete()

    book_cover = manager.dialog_data.get("book_cover")
    book_title = manager.dialog_data.get("book_title")
    book_post = manager.dialog_data.get("book_post")
    manager.dialog_data["quote"] = quote

    await message.answer_photo(
        FSInputFile(book_cover), caption=f"<b>{book_title}</b>\n\n{book_post}"
    )

    await manager.switch_to(AddBookSG.confirm_post)


async def confirm_post(call: types.CallbackQuery, widget: Any, manager: DialogManager):
    bot: Bot = manager.middleware_data.get("bot")
    config: Settings = manager.middleware_data.get("config")
    db_session: AsyncSession = manager.middleware_data.get("db_session")

    book_post = manager.dialog_data.get("book_post")
    book_title = manager.dialog_data.get("book_title")
    book_level = manager.dialog_data.get("book_level")
    book_cover = manager.dialog_data.get("book_cover")
    book_filename = manager.dialog_data.get("book_filename")
    quote = manager.dialog_data.get("quote")

    if widget.widget_id == "yes" or widget.widget_id == "add_to_db":
        if widget.widget_id != "add_to_db":
            try:
                await bot.send_photo(
                    config.tg_bot.channel_id,
                    FSInputFile(book_cover),
                    caption=f"<b>{book_title}</b>\n\n{book_post}",
                )
                await bot.send_document(
                    config.tg_bot.channel_id, FSInputFile(book_filename), caption=quote
                )
                await call.message.answer("Книга размещена в канале")
                logger.info(f"Книга {book_title} размещена в канале")
            except Exception as e:
                logger.exception(f"Ошибка при постинге в канал: {str(e)}")
                await call.message.answer("Не удалось выложить книгу в канал")
        try:
            await add_book(
                db_session,
                book_name=book_title,
                description=book_post,
                quote=quote,
                level=book_level,
                cover=book_cover,
                book_file_name=book_filename,
            )
            logger.info(f"Книга {book_title} добавлена в бд")
            await call.message.answer("Книга добавлена в бд")
        except Exception as e:
            logger.exception(f"Ошибка при добавлении книги: {str(e)}")
            await call.message.answer("Не удалось добавить книгу в бд")
        await call.message.delete()
    else:
        await call.answer("Пост отменен")

    await manager.done()


book_post_window = Window(
    Const("Перешлите пост книги (картинка с описанием)"),
    MessageInput(process_book_post, [ContentType.DOCUMENT, ContentType.PHOTO]),
    Cancel(Const("⬅️ Назад")),
    state=AddBookSG.send_book_post,
)

book_file_window = Window(
    Const("Отправьте pdf файл книги"),
    MessageInput(process_book_file, [ContentType.DOCUMENT]),
    Back((Const("⬅️ Назад"))),
    Cancel(Const("В главное меню")),
    state=AddBookSG.send_book_file,
)


confirm_post = Window(
    Const("Подтверждаете пост?"),
    Button(Const("Да"), id="yes", on_click=confirm_post),
    Button(Const("Нет"), id="no", on_click=confirm_post),
    Button(Const("Добавить только в бд"), id="add_to_db", on_click=confirm_post),
    Back((Const("⬅️ Назад"))),
    Cancel(Const("В главное меню")),
    state=AddBookSG.confirm_post,
)


add_book_dialog = Dialog(book_post_window, book_file_window, confirm_post)
